package com.yiduo.outpost.core.web.argument;

import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author yanwen
 */
public final class QueryWrapperDecorators {

    public static void decorateParams(List<FilteringParam> params, QueryWrapperDecorator decorator) {
        if (decorator == null) {
            return;
        }
        if (StringUtils.hasText(decorator.field())) {
            injectField(params, decorator);
        }
        if (decorator.mappers().length > 0) {
            mapParamField(params, decorator);
        }
    }

    private static void injectField(List<FilteringParam> params, QueryWrapperDecorator decorator) {
        FilteringParam filteringParam = new FilteringParam()
            .setOperator(decorator.operator())
            .setLogic(decorator.logic())
            .setField(decorator.field());
        if (decorator.booleans().length > 0) {
            Boolean[] booleans = new Boolean[decorator.booleans().length];
            Arrays.setAll(booleans, i -> decorator.booleans()[i]);
            filteringParam.setValues(booleans);
        } else if (decorator.strings().length > 0) {
            filteringParam.setValues(decorator.strings());
        } else if (decorator.ints().length > 0) {
            Integer[] ints = new Integer[decorator.ints().length];
            Arrays.setAll(ints, i -> decorator.ints()[i]);
            filteringParam.setValues(ints);
        }
        params.add(0, filteringParam);
    }

    private static void mapParamField(List<FilteringParam> params, QueryWrapperDecorator decorator) {
        Map<String, String> fieldMapper = Arrays.stream(decorator.mappers()).collect(Collectors.toMap(QueryWrapperMapper::from, QueryWrapperMapper::to));
        Iterator<FilteringParam> paramIterator = params.iterator();
        while (paramIterator.hasNext()) {
            FilteringParam param = paramIterator.next();
            String field = param.getField();
            if (fieldMapper.containsKey(field)) {
                param.setField(fieldMapper.get(field));
            } else {
                if (decorator.restrict()) {
                    paramIterator.remove();
                }
            }
        }
    }
}
